package org.server.task;

import com.alibaba.fastjson.JSON;
import com.iohao.game.widget.light.timer.task.AbstractTimerTask;
import com.iohao.game.widget.light.timer.task.TimerTaskRegion;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.server.action.ActionCmd;
import org.server.common.BroadcastUtils;
import org.server.common.RedisUtil;
import org.server.domain.Login.MyAttachment;
import org.server.domain.Result.Msg;
import org.server.service.LoginService;
import org.server.service.RoomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

@Slf4j
@Component
@Accessors(chain = true)
public class RoomPlayingTask extends AbstractTimerTask {
    //出牌后的回合时间
    public static final Integer FINISH_TIME = 3000;
    //回合时间
    public static final Integer TURN_TIME = 20000;
    @Setter
    private List<Long> playerList;
    @Setter
    private String roomName;
    @Setter
    private RedisUtil redisUtil;
    @Setter
    private LoginService loginService;

    /**
     * 子类提供的 定时任务存储器
     *
     * @return 定时任务存储器
     */
    @Override
    protected TimerTaskRegion getTimerTaskRegion() {
        return TimerTaskEnum.ROOM_PLAYING;
    }

    /**
     * 执行方法
     * <pre>
     *     时间到就执行, 否则就不执行
     * </pre>
     */
    @Override
    public void execute() {
        log.error("开始结算回合");
        Long current = Long.valueOf(redisUtil.getValueInHash(roomName, RoomService.CURRENT).toString());

        //判断玩家是否达到获胜的条件
        List<Integer> poker = JSON.parseArray(redisUtil.getValueInHash(roomName, current.toString()).toString(), Integer.class);
        if (poker.size() == 0) {
            MyAttachment myAttachment = loginService.getMyAttachment(current);
            BroadcastUtils.broadcast(ActionCmd.POKER, ActionCmd.POKER_WIN, new Msg(current.toString()), playerList);
            BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg(myAttachment.getUserNickName() + "获胜"), playerList);
            //设置房间的准备人数
            redisUtil.setHash(roomName, RoomService.READY, RoomService.MIN_PLAYER);
            //设置房间存活时间为5min
            redisUtil.expire(roomName, RoomService.ALIVE_TIME);
            //初始化牌堆
            redisUtil.setHash(roomName, RoomService.DECK, JSON.toJSONString(new Stack<>()));
            //初始化真假堆
            redisUtil.setHash(roomName, RoomService.TRUE_OR_FALSE, JSON.toJSONString(new ArrayList<>()));
            //设置房间的初始状态
            redisUtil.setHash(roomName, RoomService.STATUS, RoomService.ROOM_IDLE);
            return;
        }

        log.info("{}", playerList);
        //计算下一个出牌的玩家
        int indexOf = (playerList.indexOf(current) + 1) % playerList.size();
        current = playerList.get(indexOf);
        redisUtil.setHash(roomName, RoomService.CURRENT, current);

        //清空牌堆
        Integer pass = (Integer) redisUtil.getValueInHash(roomName, RoomService.PASS);
        log.error("pass:{},{}", pass, pass.compareTo(RoomService.MAX_PASS));
        //过牌人数达到三个则清理牌堆
        if (pass.compareTo(RoomService.MAX_PASS) >= 0) {
            pass = RoomService.MIN_PASS;
            redisUtil.setHash(roomName, RoomService.DECK, JSON.toJSONString(new Stack<>()));
            redisUtil.setHash(roomName, RoomService.PASS, RoomService.MIN_PASS);
            redisUtil.setHash(roomName, RoomService.TRUE_OR_FALSE, JSON.toJSONString(new ArrayList<>()));
            redisUtil.setHash(roomName, RoomService.CURRENT_FAKER_CARD, "");
        }
        //更新过牌人数（默认下一个玩家是过牌，如果下一位玩家出了牌，则将pass置0）
        redisUtil.setHash(roomName, RoomService.PASS, pass + 1);

        //通知玩家
        MyAttachment myAttachment = loginService.getMyAttachment(current);
        String name = myAttachment.getUserNickName();
        BroadcastUtils.broadcast(ActionCmd.MSG, ActionCmd.MSG_BROADCAST, new Msg("轮到玩家" + name + "出牌了"), playerList);
        BroadcastUtils.broadcast(ActionCmd.POKER, ActionCmd.POKER_YOUR_TURN, new Msg(current.toString()), playerList);
        BroadcastUtils.broadcast(ActionCmd.ROOM, ActionCmd.ROOM_TIMER_ON, new Msg(), playerList);

        Stack<List<Integer>> deck = new Stack<>();
        String deckInRedis = redisUtil.getValueInHash(roomName, RoomService.DECK).toString();
        if (deckInRedis != null) {
            for (Integer[] ints : JSON.parseArray(deckInRedis, Integer[].class)) {
                deck.push(Arrays.asList(ints));
            }
        }
        int nums = deck.size() == 0 ? 0 : deck.peek().size();
        Object object = redisUtil.getValueInHash(roomName, RoomService.CURRENT_FAKER_CARD);
        String currentCard = object == null ? null : object.toString();
        //告诉玩家牌堆中的出牌数量（玩家每回合出的牌算一个）
        BroadcastUtils.broadcast(ActionCmd.POKER, ActionCmd.POKER_DECK_NUM, new Msg(Integer.toString(nums)), playerList);
        //每回合给所有玩家通知本轮报的什么牌
        BroadcastUtils.broadcast(ActionCmd.POKER, ActionCmd.POKER_CURRENT_FAKER_CARD, new Msg(currentCard), playerList);

        new RoomPlayingTask()
                .setPlayerList(playerList)
                .setRoomName(roomName)
                .setRedisUtil(redisUtil)
                .setLoginService(loginService)
                .setCacheKey(roomName)
                .setDelayExecutionTime(RoomPlayingTask.TURN_TIME)
                .task();
    }

    /**
     * 取消定时任务
     */
    @Override
    public void cancel() {
    }
}
